package com.mugui;

import java.lang.reflect.Method;

public abstract interface Mugui {
	public default Object invokeFunction(String name, Object... objects) throws Exception {

		Class<?>[] classes = null;
		if (objects != null && objects.length > 0) {
			classes = new Class<?>[objects.length];
			for (int i = 0; i < classes.length; i++) {
				if (objects[i] == null) {
					classes[i] = null;
				} else {

					classes[i] = objects[i].getClass();
				}
			}
		}
		Method method = null;
		if (classes == null) {
			method = this.getClass().getMethod(name);
		} else {
			Method methods[] = this.getClass().getMethods();
			for (Method m : methods) {
				if (!m.getName().equals(name)) {
					continue;
				}
				Class<?>[] classes_t = m.getParameterTypes();
				if (classes_t.length == 0 || classes.length != classes_t.length)
					continue;
				boolean bool = true;
				for (int i = 0; i < classes_t.length; i++) {
					if (classes[i] == null)
						continue;
					if (!classes_t[i].isAssignableFrom(classes[i])) {
						if (Number.class.isAssignableFrom(classes[i])) {
							if (classes[i] == Integer.class) {
								classes[i] = int.class;
							} else if (classes[i] == Double.class) {
								classes[i] = double.class;
							} else if (classes[i] == Long.class) {
								classes[i] = long.class;
							} else if (classes[i] == Float.class) {
								classes[i] = float.class;
							} else if (classes[i] == Byte.class) {
								classes[i] = byte.class;
							}
						} else if (classes[i] == Character.class) {
							classes[i] = char.class;
						} else if (classes[i] == Boolean.class) {
							classes[i] = boolean.class;
						}
						if (!classes_t[i].isAssignableFrom(classes[i])) {
							bool = false;
							break;
						}
					}
				}
				if (bool) {
					method = m;
					break;
				}

			}

		}
		if (method == null) {
			throw new NullPointerException(getClass().getName() + " not find Method: " + name);
		}
		method.setAccessible(true);
		return classes == null ? method.invoke(this) : method.invoke(this, objects);
	}

}
